<template>
  <div class="chat-window">
    <!-- Chat Header -->
    <div class="chat-header">
      <div v-if="conversation" class="user-info">
        <span class="username">{{ otherUser.name }}</span>
      </div>
      <div v-else class="placeholder">
        <span>Please select a chat</span>
      </div>
    </div>

    <!-- Chat Content Area -->
    <div
        class="chat-content"
        ref="chatContent"
        @scroll="handleScroll"
    >
      <el-empty v-if="!conversation" description="Select a contact to start chatting" />

      <template v-else>
        <div v-if="loading" class="loading-container">
          <el-skeleton :rows="3" animated />
        </div>

        <div v-else-if="messages.length === 0" class="empty-conversation">
          <el-empty description="No messages yet" />
        </div>

        <template v-else>
          <div v-if="hasMoreMessages" class="load-more">
            <el-button
                :loading="loadingMore"
                link
                @click="loadMoreMessages"
            >
              Load more
            </el-button>
          </div>

          <ChatMessage
              v-for="(message, index) in messages"
              :key="message.id"
              :message="message"
              :show-sender="shouldShowSender(message, index)"
          />
        </template>
      </template>
    </div>

    <!-- Chat Input Area -->
    <div class="chat-input" v-if="conversation">
      <div class="input-area">
        <el-input
            v-model="messageContent"
            type="textarea"
            :autosize="{ minRows: 2, maxRows: 5 }"
            placeholder="Type a message..."
            @keydown.enter.exact.prevent="sendMessage"
        />
      </div>
      <div class="action-buttons">
        <!-- File Upload Button -->
        <el-upload
            ref="upload"
            class="file-upload"
            action="#"
            :auto-upload="false"
            :show-file-list="false"
            :on-change="handleFileSelected"
        >
          <el-button type="primary" :icon="Upload" plain class="upload-btn">
            File
          </el-button>
        </el-upload>

        <el-button
            type="primary"
            :disabled="!messageContent.trim() && !selectedFile"
            @click="sendMessage"
            :loading="sending"
        >
          Send
        </el-button>
      </div>

      <!-- Display selected file -->
      <div v-if="selectedFile" class="selected-file">
        <span class="file-name">{{ selectedFile.name }}</span>
        <span class="file-size">({{ formatFileSize(selectedFile.size) }})</span>
        <el-button
            type="danger"
            :icon="Delete"
            circle
            plain
            size="small"
            @click="clearSelectedFile"
        />
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, watch, nextTick, onMounted, onUnmounted } from 'vue';
import { useChatStore } from '../../stores/chat';
import { useUserStore } from '../../stores/user';
import ChatMessage from './ChatMessage.vue';
import chatService from '../../services/chat';
import type { ChatMessage as ChatMessageType } from '../../services/chat';
import { Upload, Delete } from '@element-plus/icons-vue';
import { ElNotification } from 'element-plus';

// Component properties
const props = defineProps<{
  conversationId?: number;
}>();

// Component events
const emit = defineEmits<{
  (e: 'messageSent'): void;
}>();

// Store
const chatStore = useChatStore();
const userStore = useUserStore();

// State variables
const messageContent = ref('');
const chatContent = ref<HTMLElement | null>(null);
const loading = ref(false);
const sending = ref(false);
const loadingMore = ref(false);
const hasMoreMessages = ref(true);
const firstMessageId = ref<number | null>(null);
const selectedFile = ref<File | null>(null);
const upload = ref<any>(null);

// Compute the current conversation
const conversation = computed(() => {
  if (!props.conversationId) return null;
  return chatStore.conversations.find(c => c.id === props.conversationId) || null;
});

// Get other user information
const otherUser = computed(() => {
  if (!conversation.value) return { id: 0, name: '', avatar: '' };

  const currentUserId = userStore.userId;
  return conversation.value.user1.id === currentUserId
      ? conversation.value.user2
      : conversation.value.user1;
});

// Get message list
const messages = computed(() => {
  if (!props.conversationId) return [];
  return chatStore.getMessagesForConversation(props.conversationId);
});

// Determine whether the sender's name should be displayed (only displayed on the first of consecutive messages)
const shouldShowSender = (message: ChatMessageType, index: number) => {
  if (index === 0) return true;

  const prevMessage = messages.value[index - 1];
  return prevMessage.senderId !== message.senderId;
};

// Listen for message scrolling
const handleScroll = () => {
  if (!chatContent.value) return;

  const { scrollTop } = chatContent.value;

  // Automatically load more messages when scrolling near the top
  if (scrollTop < 50 && hasMoreMessages.value && !loadingMore.value) {
    loadMoreMessages();
  }
};

// Load more messages
const loadMoreMessages = async () => {
  if (!props.conversationId || !firstMessageId.value || loadingMore.value || !hasMoreMessages.value) return;

  loadingMore.value = true;

  try {
    // Record the current scroll position and height
    const { scrollHeight } = chatContent.value!;

    // Load earlier messages
    const loadedCount = await chatStore.loadOlderMessages(props.conversationId, firstMessageId.value);

    if (loadedCount === 0 || loadedCount < 20) {
      hasMoreMessages.value = false;
    }

    // Wait for DOM to update
    await nextTick();

    // Keep scroll position (considering the height of the new content)
    if (chatContent.value) {
      const newScrollHeight = chatContent.value.scrollHeight;
      chatContent.value.scrollTop = newScrollHeight - scrollHeight;
    }

    // Update first message ID
    updateFirstMessageId();
  } catch (error) {
    console.error('Failed to load more messages:', error);
  } finally {
    loadingMore.value = false;
  }
};

// Update first message ID
const updateFirstMessageId = () => {
  if (messages.value.length > 0) {
    firstMessageId.value = messages.value[0].id;
  }
};

// Send message
const sendMessage = async () => {
  if ((!messageContent.value.trim() && !selectedFile.value) || !props.conversationId || sending.value) return;

  sending.value = true;

  try {
    // If there is a file, send a file message
    if (selectedFile.value) {
      await chatService.sendFileMessage(
          otherUser.value.id,
          selectedFile.value,
          messageContent.value.trim()
      );

      // Clear selected file
      clearSelectedFile();
    } else {
      // Send plain text message
      await chatStore.sendMessage(otherUser.value.id, messageContent.value.trim());
    }

    // Clear message content
    messageContent.value = '';
    emit('messageSent');

    // Scroll to the bottom
    await nextTick();
    scrollToBottom();
  } catch (error) {
    console.error('Failed to send message:', error);
    ElNotification({
      title: 'Send Failed',
      message: error instanceof Error ? error.message : 'Failed to send message, please try again',
      type: 'error'
    });
  } finally {
    sending.value = false;
  }
};

// Handle file selection
const handleFileSelected = (file: any) => {
  selectedFile.value = file.raw;

  // If the file is too large, display a warning
  if (file.size > 20 * 1024 * 1024) { // 20MB
    ElNotification({
      title: 'File Too Large',
      message: 'File size cannot exceed 20MB',
      type: 'warning'
    });
  }
};

// Clear selected file
const clearSelectedFile = () => {
  selectedFile.value = null;
  if (upload.value) {
    upload.value.clearFiles();
  }
};

// Format file size
const formatFileSize = (bytes: number) => {
  if (bytes < 1024) {
    return bytes + ' B';
  } else if (bytes < 1024 * 1024) {
    return (bytes / 1024).toFixed(1) + ' KB';
  } else if (bytes < 1024 * 1024 * 1024) {
    return (bytes / (1024 * 1024)).toFixed(1) + ' MB';
  } else {
    return (bytes / (1024 * 1024 * 1024)).toFixed(1) + ' GB';
  }
};

// Scroll to the bottom
const scrollToBottom = () => {
  if (chatContent.value) {
    chatContent.value.scrollTop = chatContent.value.scrollHeight;
  }
};

// Handle new message callback
const handleNewMessage = (message: ChatMessageType) => {
  // If it is a message for the current conversation, scroll to the bottom
  if (message.conversationId === props.conversationId) {
    nextTick(() => {
      scrollToBottom();
    });
  }
};

// Load conversation messages
const loadConversationMessages = async () => {
  if (!props.conversationId) return;

  loading.value = true;

  try {
    // Set the active conversation
    await chatStore.setActiveConversation(props.conversationId);

    // Update first message ID
    updateFirstMessageId();

    // Scroll to the bottom
    await nextTick();
    scrollToBottom();
  } catch (error) {
    console.error('Failed to load conversation messages:', error);
  } finally {
    loading.value = false;
  }
};

// Listen for conversationId changes
watch(() => props.conversationId, (newId) => {
  if (newId) {
    hasMoreMessages.value = true;
    loadConversationMessages();
  }
}, { immediate: true });

// Component mounted
onMounted(() => {
  // Register message listener
  const unsubscribe = chatService.onMessage(handleNewMessage, props.conversationId);

  // Cancel listener when component is unmounted
  onUnmounted(() => {
    if (unsubscribe) unsubscribe();
  });
});
</script>

<style scoped>
.chat-window {
  display: flex;
  flex-direction: column;
  height: 100%;
  background-color: #f5f5f5;
  overflow: hidden !important;
  position: relative;
}

.chat-header {
  padding: 16px;
  background-color: #fff;
  border-bottom: 1px solid #e0e0e0;
  display: flex;
  align-items: center;
  flex-shrink: 0;
  z-index: 10;
  height: 64px; /* Match the height of the sidebar header */
  box-shadow: 0 1px 2px rgba(0,0,0,0.05);
}

.user-info {
  display: flex;
  align-items: center;
}

.username {
  font-weight: 500;
  font-size: 16px;
  margin-left: 10px;
}

.placeholder {
  color: #999;
  font-style: italic;
}

.chat-content {
  flex: 1;
  overflow-y: auto;
  padding: 16px;
  background-color: #f9f9f9;
}

.chat-input {
  background-color: #fff;
  border-top: 1px solid #e0e0e0;
  padding: 16px;
  display: flex;
  flex-direction: column;
  flex-shrink: 0;
}

.input-area {
  margin-bottom: 8px;
}

.action-buttons {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.file-upload {
  margin-right: auto;
}

.upload-btn {
  display: flex;
  align-items: center;
}

.selected-file {
  display: flex;
  align-items: center;
  margin-top: 8px;
  padding: 8px;
  background-color: #f0f0f0;
  border-radius: 4px;
}

.file-name {
  font-weight: 500;
  margin-right: 8px;
  max-width: 300px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.file-size {
  color: #999;
  font-size: 12px;
  margin-right: auto;
}

.load-more {
  text-align: center;
  margin-bottom: 16px;
}

.loading-container {
  padding: 16px;
}

.empty-conversation {
  display: flex;
  height: 100%;
  justify-content: center;
  align-items: center;
}

.read-icon {
  margin-left: 4px;
  font-size: 12px;
  color: #67c23a;
}
</style>